// This is the main DLL file.

#include "NxCoreCache.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Globalization;

namespace Tradex {
	namespace Connectivity {
		namespace NxCore {

			NxCoreCache::NxCoreCache (NxCoreGetDefinedString pfNxCoreGetDefinedString) {
				//_InstrumentKey2InstrumentCache = gcnew Dictionary<InstrumentKey ^, InstrumentCache^> (4096);

 				List<String^>^ pStringList = gcnew List<String^> (4096);
				// Step 1: Exchanges. Yes, there is a list. Yes, it is static. No, we dont even get a string on every symbol, only the index.
				// Ergo, we need to preload this table now.
				for (int i = 0;; i++) {
					const char* exchange = pfNxCoreGetDefinedString (NxST_EXCHANGE, i);
					if (exchange == nullptr) {
						break;
					}
					String^ string = gcnew String (exchange);
					int sepIndex = string->IndexOf ('|');
					string = string->Substring (0, sepIndex)->Trim ();
					pStringList->Add (string);
				}
				_Markets = pStringList->ToArray ();
				pStringList->Clear ();

				_InstrumentData = gcnew array<List<InstrumentCache^>^> (_Markets->Length);
				for (int i = 1; i < _Markets->Length; i++) {
					_InstrumentData[i] = gcnew List<InstrumentCache^> ();					
				}
			};

			String^ NxCoreCache::GetMarket (int index) {
				return _Markets[index];
			}

			void NxCoreCache::SetTimestamp (const NxCoreSystem* nxCoreSys) {
				DateTime timestamp;
				if (nxCoreSys->nxTime.Hour != 24) {
					timestamp = DateTime (
						nxCoreSys->nxDate.Year, nxCoreSys->nxDate.Month, nxCoreSys->nxDate.Day,
						nxCoreSys->nxTime.Hour, nxCoreSys->nxTime.Minute, nxCoreSys->nxTime.Second, nxCoreSys->nxTime.Millisecond
					);
				} else {
					timestamp = DateTime (
						nxCoreSys->nxDate.Year, nxCoreSys->nxDate.Month, nxCoreSys->nxDate.Day,
						0, nxCoreSys->nxTime.Minute, nxCoreSys->nxTime.Second, nxCoreSys->nxTime.Millisecond
					);
					timestamp = timestamp.AddHours(24);
				}
				timestamp = timestamp.AddHours (nxCoreSys->nxTime.TimeZone * -1);
				_Timestamp = timestamp;
			}

			InstrumentCache^ NxCoreCache::GetInstrumentCache (const NxCoreSystem* nxCoreSys, const NxCoreMessage* nxCoreMsg, const int symbolAtom32) {
				const NxString* stringSymbol = nxCoreMsg->coreHeader.pnxStringSymbol;
				
				if(_InstrumentData[nxCoreMsg->coreHeader.ListedExg]->Count <= symbolAtom32) {
					_InstrumentData[nxCoreMsg->coreHeader.ListedExg]->Capacity = symbolAtom32;
					while (_InstrumentData[nxCoreMsg->coreHeader.ListedExg]->Count <= symbolAtom32) {
						_InstrumentData[nxCoreMsg->coreHeader.ListedExg]->Add (nullptr);
					}
				}

				InstrumentCache^ item = _InstrumentData[nxCoreMsg->coreHeader.ListedExg][symbolAtom32];
				if (item == nullptr) {
					item = gcnew InstrumentCache ();
					_InstrumentData[nxCoreMsg->coreHeader.ListedExg][symbolAtom32] = item;
					String^ market = GetMarket(nxCoreMsg->coreHeader.ListedExg);
					item->SetInstrumentBasics (market, nxCoreSys, nxCoreMsg);
				}
				return item;

			}

		}
	}
}